#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include "MQTTClient.h"

#define BROKER_ADDRESS "tcp://iot.ranye-iot.net:1883"   // 服务器ip
#define CLIENTID "qwer1234" //客户端 id
#define USERNAME "wangmeng" //用户名
#define PASSWORD "940416" //密码

#define WILL_TOPIC  "dt_mqtt/will"      // 遗嘱主题
#define LED_TOPIC   "dt_mqtt/led"       // LED主题
#define TEMP_TOPIC  "dt_mqtt/temp"      // 温度主题

// 连接回调函数
static void connlost(void *contest, char *cause)
{
    printf("\n连接服务器失败\n");
    printf("失败原因：%s\n", cause);
}

// 接收回调函数
static int msgarrvd(void *contest, char *topicName, int topicLen, MQTTClient_message *message)
{
    if (!strcmp(topicName, LED_TOPIC)) {    // 验证消息主题
        int num = atoi(message->payload);   
        switch (num) {
            case 2:
                // 设置为呼吸灯模式
                system("echo heartbeat > /sys/class/leds/sys-led/trigger");
                break;

            case 1:
                // 常亮
                system("echo none > /sys/class/leds/sys-led/trigget");
                system("echo 1 > /sys/class/leds/sys-led/brightness");
                break;
            
            case 0:
                // 熄灭
                system("echo none > /sys/class/leds/sys-led/trigget");
                system("echo 0 > /sys/class/leds/sys-led/brightness");
                break;

            default:
               
                break;
        }

        // 释放占用的内存空间
        MQTTClient_freeMessage(&message);
        MQTTClient_free(topicName);
    }

    return 1;
}

int main(int argc, char *argv) 
{

    MQTTClient client;
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;    // 链接客户端初始化
    MQTTClient_message pubmsg = MQTTClient_message_initializer;                     // 发送
    MQTTClient_willOptions will_opts = MQTTClient_willOptions_initializer;          // 遗嘱
    int rc;

    // 创建客户端对象
    rc = MQTTClient_create(client, BROKER_ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    if (rc != MQTTCLIENT_SUCCESS) {
        printf("创建客户端对象失败，错误码为： %d\n", rc);
        rc = EXIT_FAILURE;

        // 客户端创建失败 退出
        goto exit;
    }

    // 设置回调函数
    rc = MQTTClient_setCallbacks(client, NULL, connlost, msgarrvd, NULL);
    if (rc != MQTTCLIENT_SUCCESS) {
        printf("回调函数设置失败，错误码为：%d \n", rc);
        rc = EXIT_FAILURE;
        // 此时客户端创建成功，退出时需要 销毁客户端
        goto destroy_exit;
    }

    // 连接服务器
    will_opts.topicName = WILL_TOPIC;
    will_opts.message = "Unexpected disconnection";
    will_opts.retained = 1;
    will_opts.qos = 0;

    conn_opts.will = &will_opts;
    conn_opts.keepAliveInterval = 30;
    conn_opts.cleansession = 0;
    conn_opts.username = USERNAME;
    conn_opts.password = PASSWORD;

    rc = MQTTClient_connect(client, &conn_opts);
    if (rc != MQTTCLIENT_SUCCESS) {
        printf("服务器连接失败，错误码为：%d \n", rc);

        goto destroy_exit;
    }

    printf("MQTT 服务器连接成功 \n");

    // 发布上线消息
    pubmsg.payload = "Online";
    pubmsg.payloadlen = 6;
    pubmsg.qos = 0;
    pubmsg.retained = 1;

    rc = MQTTClient_publishMessage(client, WILL_TOPIC, &pubmsg, NULL);
    if (rc != MQTTCLIENT_SUCCESS) {
        printf("消息发送失败，返回码：%d \n",rc);
        rc = MQTTCLIENT_FAILURE;

        goto disconnect_exit;
    }

    // 订阅主题
    rc = MQTTClient_subscribe(client, LED_TOPIC, 0);
    if (rc != MQTTCLIENT_SUCCESS) {
        printf("订阅失败，错误码：%d\n", rc);
        rc = MQTTCLIENT_FAILURE;
        goto disconnect_exit;
    }

    // 向服务端发送温度信息
    while (1) {
        MQTTClient_message tempmsg = MQTTClient_message_initializer;

        char temp_str[10] = {0};
        int fd;

        fd = open("/sys/class/thermal/thermal_zone0/temp", O_RDONLY);
        if (fd < 0) {
            printf("温度文件打开失败\n");
        } 
        read(fd, temp_str, sizeof(temp_str));
        close(fd);

        // 发布温度信息
        tempmsg.payload = temp_str;
        tempmsg.payloadlen = sizeof(temp_str);
        tempmsg.qos = 0;
        tempmsg.retained = 1;

        rc = MQTTClient_publishMessage(client, TEMP_TOPIC, &tempmsg, NULL);
        if (rc != MQTTCLIENT_SUCCESS) {
            printf("温度发送失败\n");
            rc = MQTTCLIENT_FAILURE;
            goto unsubscribe_exit;
        }

        sleep(30);
    }

// 取消 led 主题订阅
unsubscribe_exit:
    rc = MQTTClient_unsubscribe(client, LED_TOPIC);
    if (rc != MQTTCLIENT_SUCCESS) {
        printf("取消订阅失败， 错误码：%d\n");
        rc = MQTTCLIENT_FAILURE;
    }

// 连接失败 断开服务
disconnect_exit:
    rc = MQTTClient_disconnect(client, 10000);
    if (rc != MQTTCLIENT_SUCCESS) {
        printf("断开服务失败，错误码：%d\n");
        rc = MQTTCLIENT_FAILURE;
    }

// 销毁客户端
destroy_exit:
    MQTTClient_destroy(&client);

exit:
    return rc;
}

